package cn.supermarket.service.impl;

import cn.supermarket.ex.ServiceException;
import cn.supermarket.mapper.VipMapper;
import cn.supermarket.pojo.dto.AddVipDTO;
import cn.supermarket.pojo.dto.VipInfoDTO;
import cn.supermarket.pojo.entity.Vip;
import cn.supermarket.pojo.vo.VipSimpleVO;
import cn.supermarket.service.iservice.IVIPService;
import cn.supermarket.utils.SnowFlakeGenerateIdWorker;
import cn.supermarket.web.State;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author theThe
 */
@Transactional(rollbackFor = {})
@Service
public class VipServiceImpl implements IVIPService {

    @Autowired
    private VipMapper vipMapper;


    /**
     * 注册会员
     *
     * @param addVipDTO 用户填写的会员信息
     */
    @Override
    public void regVip(AddVipDTO addVipDTO) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = vipMapper.getVipSimpleByPhone(addVipDTO.getPhone());
        // 判断会员是否已存在
        if (vipSimpleVO != null) {
            // 已存在,抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "该手机号已经注册会员");
        }
        // 不存在,执行下面语句
        Vip vip = new Vip();
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 复制addVipDTO对象的同名属性到vip对象
        BeanUtils.copyProperties(addVipDTO, vip);
        // 雪花算法生成随机id
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker = new SnowFlakeGenerateIdWorker(0L, 0L);
        long id = snowFlakeGenerateIdWorker.nextId();
        // 补全vip对象的信息
        vip.setId(id);
        vip.setStoredValueCardNumber(addVipDTO.getPhone());
        vip.setStoredValueCardAmount(BigDecimal.ZERO);
        vip.setIsEnable(0);
        vip.setIsDisplay(1);
        vip.setIsCancel(0);
        vip.setGmtCreate(now);
        vip.setGmtModify(now);
        // 执行添加
        int rows = vipMapper.addVip(vip);
        // 如果受影响的行数不为1,抛出异常
        if (rows != 1) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "添加失败,请重试");
        }
    }

    /**
     * 根据手机号查询会员信息
     *
     * @param phone 手机号
     * @return 会员信息
     */
    @Override
    public VipSimpleVO getVipSimpleByPhone(String phone) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = vipMapper.getVipSimpleByPhone(phone);
        // 判断会员是否未存在
        if (vipSimpleVO == null) {
            // 未存在,抛出异常
            throw new ServiceException(State.ERR_NOT_FOUND, "当前手机号未注册会员");
        }
        // 返回会员信息
        return vipSimpleVO;
    }

    /**
     * 修改会员信息
     *
     * @param vipInfoDTO 会员信息
     */
    @Override
    public void updateVipInfo(VipInfoDTO vipInfoDTO) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = getVipSimpleByPhone(vipInfoDTO.getOldPhone());
        // 执行修改
        vipMapper.updateVipInfo(vipInfoDTO);
    }

    /**
     * 根据手机号充值会员储值卡余额
     *
     * @param phone  手机号
     * @param amount 需要充值的金额
     */
    @Override
    public void addAmount(String phone, BigDecimal amount) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = getVipSimpleByPhone(phone);
        // 获取会员储值卡当前余额
        BigDecimal storedValueCardAmount = vipSimpleVO.getStoredValueCardAmount();
        // 判断需要充值的金额是否合法
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            // 如果小于0,抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "你输入的金额错误,请重新输入");
        }
        // 在余额的基础上添加需要充值的金额
        BigDecimal storedValueCardNewAmount = storedValueCardAmount.add(amount);
        // 根据手机号修改余额
        int rows = vipMapper.updateAmount(phone, storedValueCardNewAmount);
        // 如果受影响的行数不为1,抛出异常
        if (rows != 1) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "充值失败,请重试");
        }
    }

    /**
     * 根据手机号消费会员储值卡余额
     *
     * @param phone  手机号
     * @param amount 需要消费的金额
     */
    @Override
    public void subAmount(String phone, BigDecimal amount) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = getVipSimpleByPhone(phone);
        // 获取会员储值卡当前余额
        BigDecimal storedValueCardAmount = vipSimpleVO.getStoredValueCardAmount();
        // 在余额的基础上减去需要消费的金额
        BigDecimal storedValueCardNewAmount = storedValueCardAmount.subtract(amount);
        // 判断需要消费的金额是否合法
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            // 如果小于0,抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "你输入的金额错误,请重新输入");
        }
        // 判断消费之后是否小于0
        if (storedValueCardNewAmount.compareTo(BigDecimal.ZERO) < 0) {
            // 如果小于0,代表余额不足,抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "你的余额不足,请充值");
        }
        // 根据手机号修改余额
        int rows = vipMapper.updateAmount(phone, storedValueCardNewAmount);
        // 如果受影响的行数不为1,抛出异常
        if (rows != 1) {
            throw new ServiceException(State.ERR_BAD_REQUEST, "充值失败,请重试");
        }
    }

    /**
     * 通过会员手机号注销会员
     *
     * @param phone 会员手机号
     */
    @Override
    public void updateCancel(String phone) {
        // 根据手机号查询会员信息
        VipSimpleVO vipSimpleVO = getVipSimpleByPhone(phone);
        // 执行删除
        int rows = vipMapper.deleteVip(phone);
        // 判断会员有没有被注销
        if (rows != 1) {
            // 如果被注销抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "当前会员已注销");
        }
    }

    /**
     * 查询全部会员
     *
     * @return 会员列表
     */
    @Override
    public List<VipSimpleVO> getVipList() {
        // 执行查询
        List<VipSimpleVO> list = vipMapper.getAllVips();
        // 判断查询结果是否为空
        if (list == null) {
            // 如果空,抛出异常
            throw new ServiceException(State.ERR_BAD_REQUEST, "暂无会员");
        }
        // 返回查询到的会员集合
        return list;
    }
}
